﻿using System;
using EmbeddedSharp.Core;
using EmbeddedSharp.Scripting;
using Zove.Runtime;

namespace Zove.Scripting.Modelling {

    /// <summary>
    /// Produce an expression for the factor.
    /// </summary>
    [Function("formulate", "Formulate an expression for the factor.", 
        "circle c;\n\rc.r=10;\n\rarea=formulate(c.area);", "area==3.1415926*r^2")]
    public class FormulateNode : ZoveScriptingContextFuncNode {

        /// <summary>
        /// Default constructor
        /// </summary>
        public FormulateNode()
            : base() {
            base.Value = "formulate";
        }

        /// <summary>
        /// Produce the expression.
        /// </summary>
        /// <returns>the resultant expression</returns>
        public override object Evaluate() {
            if (Parameters.Count < 1) {
                throw new ArgumentException(
                    "usage: formulate(factor)");
            }

            RuntimeFactor factor
                = ZoveShellContext.GetFactor(
                Parameters[Parameters.Count - 1].Value);
            if (factor.Status == RuntimeFactorStatus.Unknown) {
                throw new Exception(
                    string.Format(
                    "Cannot produce an expression for factor '{0}' due to its unknown status.",
                    factor.QualifiedName));
            }

            string instanceName = factor.Model.Instance.Name;
            SolutionFormulator ss = new SolutionFormulator(factor);
            string result = ss.Parse();
            //result = Utils.Prefixize(instanceName, result,
            //    ZoveDependencyManager.Instance.FunctionManager);

            ModelInstance rm = (ModelInstance)Context.GetVariable(instanceName);
            Parser parser
                = ZoveDependencyManager.Instance.ParserFactory.CreateParser(
                result, rm.Model);
            Node root = parser.Parse();

            if (Parameters.Count < 2) {
                return root;
            } else {
                string var = Parameters[Parameters.Count - 2].Value;
                FormulateExpressionTranslator t
                    = new FormulateExpressionTranslator(var);
                string ret = t.Translate(root);
                return ret;
            }
        }

        /// <summary>
        /// Returns the formulated expression
        /// </summary>
        /// <returns></returns>
        public override string ToString() {
            return this.Evaluate().ToString();
        }
    }
}
